<?php
// +----------------------------------------------------------------------
// | User 自定义服务
// +----------------------------------------------------------------------
// | 主要服务于User数据处理
// +----------------------------------------------------------------------
// | 错误编码头 229xxx
// +----------------------------------------------------------------------

namespace common\service;

use common\exception\LogicException;
use common\model\UserConfigModel;
use common\model\UserModel;
use support\ErrorCode;
use support\SingletonTrait;

class UserService
{

    // 单例工具
    use SingletonTrait;

    /**
     * 获取用户默认密码
     * @return mixed
     */
    public function getUserDefaultPassword()
    {
        $optionsService = OptionsService::getInstance();
        $defaultOptionData = $optionsService->getOptionsData("default_settings");
        if (isset($defaultOptionData["default_password"]) && !empty($defaultOptionData["default_password"])) {
            $defaultPassword = $defaultOptionData["default_password"];
        } else {
            $defaultPassword = C('default_password');
        }
        return $defaultPassword;
    }

    /**
     * 更新当前用户系统默认配置
     * @param $userId
     * @param $param
     * @return array
     * @throws \Exception
     */
    public function updateUserSystemConfig($userId, $param)
    {
        $userConfigModel = model(UserConfigModel::class);
        // 获取用户配置ID
        $userConfigFindData = $userConfigModel->findData([
            "filter" => ['type' => 'system', 'user_id' => $userId],
            "fields" => "id"
        ]);

        if (isset($userConfigFindData["id"])) {
            // 已经存在用户系统配置则修改操作
            $resData = $userConfigModel->modifyItem([
                'id' => $userConfigFindData["id"],
                "config" => $param
            ]);
        } else {
            // 不存在新增操作
            $resData = $userConfigModel->addItem([
                'type' => 'system',
                'user_id' => $userId,
                "config" => $param
            ]);
        }
        if (!$resData) {
            // 更新用户系统配置失败错误码 - 004
            throw new LogicException($userConfigModel->getError(), ErrorCode::USER_SYSTEM_CONFIG_UPDATE_FAILURE);
        } else {
            // 更新用户语言包cookie
            return success_response($userConfigModel->getSuccessMessage(), $resData);
        }
    }

    /**
     * 获取用户自定义配置
     * @param $filter
     * @return array|mixed
     */
    public function getUserCustomConfig($filter)
    {
        $userConfigModel = model(UserConfigModel::class);
        $userConfigData = $userConfigModel->findData([
            'fields' => 'config',
            'filter' => $filter
        ]);
        return $userConfigData;
    }

    /**
     * 获取当前用户系统默认配置
     * @param $userId
     * @return array
     */
    public function getUserSystemConfig($userId)
    {
        $userConfigModel = model(UserConfigModel::class);
        $userSystemConfigData = $userConfigModel->findData([
            'fields' => 'config',
            'filter' => [
                'type' => 'system',
                'user_id' => $userId,
            ]
        ]);

        if (!$userSystemConfigData) {
            $optionsService = OptionsService::getInstance();
            $resData = $optionsService->getOptionsData("default_settings");
            return ["lang" => $resData["default_lang"], "timezone" => $resData["default_timezone"], "mfa" => 'no'];
        } else {
            return $userSystemConfigData["config"];
        }
    }

    /**
     * 通过用户uuid获取用户头像
     * @param $userUUID
     * @return array|mixed
     * @throws \Exception
     */
    public function getUserAvatarByUUID($userUUID)
    {
        $userModel = model(UserModel::class);
        $userData = $userModel->findData([
            "fields" => "id,name",
            "filter" => [
                "uuid" => $userUUID
            ]
        ]);

        if (!empty($userData)) {
            // 获取用户头像
            $mediaService = MediaService::getInstance();
            $userData['avatar'] = $mediaService->getSpecifySizeThumbPath(['link_id' => $userData['id'], 'module_id' => 34], 'origin');
            $userData['pinyin'] = generate_code($userData['name']);
            return $userData;
        } else {
            return ['avatar' => '', 'pinyin' => ''];
        }
    }

    /**
     * 获取个人信息
     * @param $userId
     * @return array
     * @throws \Exception
     */
    public function getUserInfo($userId)
    {
        // 获取用户信息
        $userModel = model(UserModel::class);
        $userData = $userModel->findData([
            "filter" => ['id' => $userId],
            "fields" => "id as user_id,name,email",
        ]);

        // 组装数据
        $loginData = [
            'user_id' => $userData['user_id'],
            'name' => $userData['name'],
            'pinyin' => generate_code($userData['name']),
//            'ip' => get_client_ip(),
        ];

        // 返回数据
        return $loginData;
    }


    /**
     * 获取用户单个字段
     * @param $filter
     * @param $field
     * @return array|mixed
     */
    public function getUserFindField($filter, $field)
    {
        return model(UserModel::class)->where($filter)->field($field)->find();
    }

    /**
     * 通过关联id拿到用户
     * @param $unionID
     * @param bool $remoteSync
     * @param string $fields
     * @return mixed
     */
    public function getUserByUnionId($unionID, $remoteSync = false, $fields = "id,phone,email,name,union_id,created,avatar,uuid,user_cert_id")
    {
        $model = model(UserModel::class);
        $user = $model->where(['union_id' => $unionID])->field($fields)->find();

        if (empty($user) && $remoteSync === true) {
            $requestData = [
                "user_id" => $unionID,
                'hide' => 'no',
            ];
            $data = teamones_request('teamones-im', 'user/get_other_user_info', $requestData)['data'];
            $loginService = LoginService::getInstance();
            $user = $loginService->syncUserBasicData($data['user'], false);
        }
        return $user;
    }

    /**
     * 通过关联id拿到用户
     * @param int $userId
     * @return array|bool|string|null
     * @throws \Exception
     */
    public function getUserByUserId(int $userId)
    {
        $user = model(UserModel::class)->where(['id' => $userId])->field('union_id')->find();
        $requestData = [
            "user_id" => $user['union_id'],
            'hide' => 'no',
        ];
        $data = teamones_request('teamones-im', 'user/get_other_user_info', $requestData)['data'];
        $loginService = LoginService::getInstance();
        $data['saas_user'] = $loginService->syncUserBasicData($data['user'], false);
        $data['saas_user_id'] = $data['saas_user']['id'];
        return $data;
    }

    /**
     * 通过关联ids拿到用户列表
     * @param array $userIdList
     * @param int $tenantId
     * @return array
     * @throws \Exception
     */
    public function getUsersByUserIds(array $userIdList, int $tenantId = 0)
    {
        $model = model(UserModel::class);
        $users = $model->where(['id' => ['IN', implode(',', $userIdList)]])->field('json', true)->select();
        $requestData = [
            "param" => [
                "filter" => [
                    "id" => ['-in', implode(',', array_column($users, 'union_id'))],
                ],
                'tenant_id' => $tenantId
            ]
        ];
        $data = teamones_request('teamones-im', 'user/get_other_users_info', $requestData)['data'];
        $users = array_column($users, null, 'union_id');
        foreach ($data as &$user) {
            $user['saas_user'] = $users[$user['user']['id']];
            $user['saas_user_id'] = $user['saas_user']['id'];
        }
        return $data;
    }

    /**
     * 通过关联ids拿到用户列表
     * @param $unionIDs
     * @param string $fields
     * @param bool $remoteSync
     * @return mixed
     */
    public function getUsersByUnionIds($unionIDs, $fields = "id,name", $remoteSync = false)
    {
        $model = model(UserModel::class);
        $users = $model->where(['union_id' => ['IN', implode(',', $unionIDs)]])->field($fields)->select();

        //查询出的用户和预期的用户数量不等 那么从远端获取一次用户
        if ($remoteSync === true && count($users) != count($unionIDs)) {
            $usersAssoc = array_column($users, null, 'union_id');
            $syncIds = array_filter($unionIDs, function ($item) use (&$usersAssoc) {
                return isset($usersAssoc[$item]) == false;
            });

            $requestData = [
                "param" => [
                    "filter" => [
                        "id" => ['-in', implode(',', $syncIds)],
                    ],
                ]
            ];
            $data = teamones_request('teamones-im', 'user/get_other_users_info', $requestData)['data'];
            $data = $data ?? [];
            $loginService = LoginService::getInstance();
            foreach ($data as $user) {
                $users[] = $loginService->syncUserBasicData($user['user'], false);
            }
        }
        return $users;
    }

    /**
     * 通过角色code 返回用户列表
     * @param $filter
     * @param null $fields
     * @return mixed
     */
    public function getUserListByRole($filter, $fields = null): array
    {
        $userData = [];
        $loginService = LoginService::getInstance();
        $userName = $filter['user_name'] ?? null;
        $departmentId = $filter['department.id'] ?? null;
        // 生成过滤条件
        $filter = [
            "param" => [
                "filter" => [
                    "role.code" => ["-in", $filter['role_code']]
                ],
            ]
        ];
        if (!empty($userName)) {
            $filter['param']['filter']['user.name'] = ['-lk', $userName];
        }
        if (!empty($departmentId)) {
            $filter['param']['filter']['department.id'] = $departmentId;
        }

        // 用户中心用户列表
        $remoteUserData = teamones_request('teamones-im', 'tenant/select_tenant_user', $filter)['data'];
        $userListLocal = $loginService->syncUserBasicDataBatch($remoteUserData);
        $userListLocal = array_column($userListLocal, null, 'union_id');
        // 同步用户信息
        foreach ($remoteUserData as $remoteUserItem) {
            $user = $userListLocal[$remoteUserItem['id']] ?? false;
            if ($user !== false) {
                $user = array_merge($remoteUserItem, $user);
                $userData[] = $user;
            }
        }
        return $userData;
    }

    /**
     * 查询用户列表
     * @param $filter
     * @param array $fields
     * @return mixed
     */
    public function selectLocalUserList($filter, $fields = ['id', 'name', 'avatar'])
    {
        return model(UserModel::class)->where($filter)->field($fields)->select();
    }

    /**
     * 设置用户资格证书
     * @param $data
     * @return mixed
     * @throws \Exception
     */
    public function setUserCert($data)
    {
        $userIdArray = $data['user_id'];
        $user = $this->getUsersByUnionIds($userIdArray, "id", true);
        if (empty($user)) {
            return [];
        }
        return model(UserModel::class)->save([
            'id' => ['IN', implode(',', array_column($user, 'id'))],
            'user_cert_id' => $data['user_cert_id'],
        ]);
    }

    /**
     * 查询成员列表
     * @param $param
     * @return array
     * @throws \Exception
     */
    public function getUserList($param): array
    {
        $loginService = LoginService::getInstance();
        // 生成过滤条件
        $param = rollback_parser_filter($param);
        // 用户中心用户列表
        $remoteUserData = teamones_request('teamones-im', 'tenant/select_tenant_user', ['param' => $param])['data'];
        // 同步用户信息
        $userListLocal = $loginService->syncUserBasicDataBatch($remoteUserData);
        $userListLocal = array_column($userListLocal, null, 'union_id');
        $userData = [];
        $userDataIdMap = [];
        foreach ($remoteUserData as $remoteUserItem) {
            $user = $userListLocal[$remoteUserItem['id']] ?? false;
            if ($user !== false) {
                $remoteUserItem['saas_user'] = $user;
                $remoteUserItem['saas_user_id'] = $user['id'];
                if (in_array($user['id'], $userDataIdMap)) {
                    continue;
                }
                $userDataIdMap[] = $user['id'];
                $userData[] = $remoteUserItem;
            }
        }
        return $userData;
    }

    /**
     * 将用户信息设置到当前请求中
     * @param string $xUserInfoHeader
     * @throws \Exception
     */
    public function parseXUserInfoAndPresetRequest(string $xUserInfoHeader)
    {
        $request = \request();
        $loginService = LoginService::getInstance();
        $XUserInfoBase = json_decode(base64_decode($xUserInfoHeader), true);
        if (!empty($XUserInfoBase) && !empty($XUserInfoBase['id']) && !empty($XUserInfoBase['tenant_id'])) {

            $userDataIn = [
                'phone' => $XUserInfoBase['phone'],
                'email' => $XUserInfoBase['email'],
                'name' => $XUserInfoBase['name'],
                'union_id' => $XUserInfoBase['id'],
                'avatar' => !empty($XUserInfoBase['avatar']) ? $XUserInfoBase['avatar'] : "",
            ];

            $userCache = $request->getUserInfoCache($XUserInfoBase['id'], $userDataIn);

            if ($userCache !== false) {
                $userData = $userCache;
            } else {
                // 同步用户信息
                $userData = $loginService->syncUserBasicData($XUserInfoBase);
                $request->setUserInfoCache($XUserInfoBase['id'], $userData);
            }


            // 设置当前module code
            $controller = to_under_score($request->controller());


            $request->getModuleCode($controller);
            $request->getTenantId($XUserInfoBase['tenant_id']);
            $request->getUserUUID($userData['uuid']);
            $request->getUserId($userData['id']);
            $request->getUnionUserId($XUserInfoBase['id']);
            $request->getXUserInfo($xUserInfoHeader);

            // 生成当前请求批次号
            $batchNumber = C('belong_system') . '_' . string_random(8) . '-' . create_uuid();
            $request->getBatchNumber($batchNumber);
        } else {
            // 错误的header头参数
            APP_DEBUG && trace("Wrong user info param.", "DEBUG");
            throw new LogicException("Wrong user info param.", ErrorCode::WRONG_USER_INFO_PARAM);
        }

    }

    /**
     * 用户ID转换
     * @param array $userId 用户id
     * @param string $in 当前输入的用户id类型 是saas 还是im
     * @param bool $map 是否返回字典
     * @return array
     */
    public function userIdTransform(array $userId, $in = 'im', $map = false)
    {
        if (empty($userId)) {
            return [];
        }

        if ($in === 'im') {
            $current = 'union_id';
            $want = 'id';
        } else if ($in === 'saas') {
            $current = 'id';
            $want = 'union_id';
        } else {
            return [];
        }

        $saasUser = model(UserModel::class)->field('id,union_id')->where([$current => ['IN', $userId]])->select();
        if (!$map) {
            return array_column($saasUser, $want);
        }
        return array_column($saasUser, $want, $current);
    }

    /**
     * 查询部门 saasUser 的department_id=>saasUserList Map
     * @param $filter
     * @return array
     */
    public function getDepartmentSaasUserMap($filter)
    {
        $param = [
            'param' => [
                'filter' => $filter
            ]
        ];
        $departmentHeadmanList = teamones_request('teamones-im', 'tenant/select_department_user_department_info_merged', $param);
        $departmentHeadmanList = $departmentHeadmanList['data']['rows'];
        $unionIdList = array_column($departmentHeadmanList, 'user_id', 'user_id');
        unset($unionIdList[0]);
        if (empty($unionIdList)) {
            return [];
        }
        $saasUserList = model(UserModel::class)->where(['union_id' => ['IN', array_values($unionIdList)]])->select();
        $saasUserList = array_column($saasUserList, null, 'union_id');
        $userDepartmentMap = [];
        foreach ($departmentHeadmanList as $departmentHeadmanItem) {
            $departmentHeadmanItem['saas_user'] = $saasUserList[$departmentHeadmanItem['user_id']] ?? null;
            if (empty($departmentHeadmanItem['saas_user'])) {
                continue;
            }
            foreach ($departmentHeadmanItem['department_info'] as $departmentInfo) {
                $userDepartmentMap[$departmentInfo['id']][] = $departmentHeadmanItem['saas_user'];
            }
        }
        return $userDepartmentMap;
    }
}
